package com.sky.aspect;

import com.sky.anno.AutoFile;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Component
@Aspect
@Slf4j
public class AutoFileAspect {


    @Pointcut("execution(* com.sky.mapper.*.*(..))" +
            " && @annotation(com.sky.anno.AutoFile)")
    public void autoFileAspect(){
    }

    @Before("autoFileAspect()")
    public void autoFile(JoinPoint joinPoint)  {
        //获取到当前被拦截方法上的数据库操作类型
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();//获取方法签名
        AutoFile autoFile = signature.getMethod().getAnnotation(AutoFile.class);//获取方法上的注解对象
        OperationType type = autoFile.value();  //获得注解对象的类型
        //获取到当前被拦截方法的参数 -- 实体对象
        Object[] args = joinPoint.getArgs();//参数个数及类型不确定 所以为object类型的数组
        if (args == null || args.length ==0){
            return;
        }
        Object entiy  = args[0];//默认参数第一个值为实体类
        //准备赋值的数据
        LocalDateTime now = LocalDateTime.now();
        Long id = BaseContext.getCurrentId();

        //根据数据库操作类型的不同 为对应的属性通过反射赋值
        if (type == OperationType.INSERT){ //如果为新增值 则要为四个属性值赋值
            try {
                Method createTime = entiy.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                Method updateTime = entiy.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method createUser = entiy.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
                Method updateUser = entiy.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                //通过方法设置属性值
                createTime.invoke(entiy,now);
                updateTime.invoke(entiy,now);
                createUser.invoke(entiy,id);
                updateUser.invoke(entiy,id);

            } catch (Exception e) {
               e.printStackTrace();
            }
        }else {
            try {
                Method updateTime = entiy.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method updateUser = entiy.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                //通过反射的方法进行赋值
                updateTime.invoke(entiy,now);
                updateUser.invoke(entiy,id);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        log.info("AOP提前通知生效了,赋值后的实体对象为:{}",entiy);
    }
}
